﻿using Orchard;
using Orchard.Caching;
using Orchard.Security;
using Orchard.Services;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace Wolf.LoggedInUsers.Services
{
    public interface ILoggedInUsersService : IDependency
    {
        void UpdateUser(IUser user);
        void UserLoggedOut(IUser user);
        void LogOutInactiveUsers();
        IEnumerable<string> GetLoggedInUsers();
    }

    public class LoggedInUsersService : ILoggedInUsersService
    {
        private const string UserListCacheEntryID = "Wolf.LoggedInUsers.CachedUserList";

        private readonly IClock _clock;
        private readonly ICacheManager _cacheManager;

        public LoggedInUsersService(IClock clock, ICacheManager cacheManager)
        {
            _clock = clock;
            _cacheManager = cacheManager;
        }

        public void UpdateUser(IUser user)
        {
            LogInOrUpdateUser(user.UserName);
        }

        public void UserLoggedOut(IUser user)
        {
            LogOutUser(user.UserName);
        }

        public void LogOutInactiveUsers()
        {
            foreach (var item in GetCachedUserList()) if (item.Value.AddMinutes(5) < _clock.UtcNow) LogOutUser(item.Key);
        }

        public IEnumerable<string> GetLoggedInUsers()
        {
            return GetCachedUserList().Keys.ToList();
        }

        private ConcurrentDictionary<string, DateTime> GetCachedUserList()
        {
            return _cacheManager.Get(UserListCacheEntryID, ctx => { return new ConcurrentDictionary<string, DateTime>(); });
        }

        private void LogInOrUpdateUser(string userName)
        {
            GetCachedUserList().AddOrUpdate(userName, _clock.UtcNow, (key, oldValue) => _clock.UtcNow);
        }

        private void LogOutUser(string userName)
        {
            (GetCachedUserList() as IDictionary).Remove(userName);
        }
    }
}